package pl.diagnoser.server.lpr;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import pl.diagnoser.client.dto.AttributeDictDTO;
import pl.diagnoser.client.dto.ObjectAttributesDTO;
import pl.diagnoser.client.dto.ObjectHistoryViewer;
import pl.diagnoser.client.dto.SymptomDTO;
import pl.diagnoser.server.persistance.dao.AttributeDictDao;
import pl.diagnoser.server.persistance.dao.ObjectAttributesDao;
import lprlibrary.io.SimpleFileDataManager;
import lprlibrary.ml.MLException;
import lprlibrary.ml.MachineLearning;
import lprlibrary.ml.Sample;
import lprlibrary.ml.Samples;

public class DiagnoserMachineLearning extends MachineLearning {
	
	private DiagnoserKnowledgeBase knowledgeBase;
    
    public DiagnoserMachineLearning(DiagnoserAttributes attributes, String file) throws FileNotFoundException {
            samples = new Samples();
            createSamples(attributes);
            loadKnowledgeBase(file);
    }
    
    private void loadKnowledgeBase(String file) throws FileNotFoundException {
            knowledgeBase = new DiagnoserKnowledgeBase();
            SimpleFileDataManager dataLoader = new SimpleFileDataManager(knowledgeBase);
            try {
                    dataLoader.setSourceFile(new FileInputStream(file));
                    dataLoader.load();
            } catch (FileNotFoundException e) {
                    e.printStackTrace();
            }
    }
    
    public void fillSamples(List<ObjectHistoryViewer> estimateView, int mode) {
            estimateView = rebuildEstimateListByMode( estimateView, mode );
            for (ObjectHistoryViewer estimate: estimateView) {
            	Sample sample = new Sample(String.valueOf(estimate.getEstimate().getId()), samples.getAttributesCount(), samples);
            	sample.setAttributeValue(0, estimate.getEstimate().getDefect());
                
            	
                for (String symptom: estimate.getSymptomsAsList()) {
                	Sample tmpSample = (Sample)sample.clone();
                    try {
                    	tmpSample.setAttributeValue(1, symptom);
                    } catch(MLException e) {
                    	System.out.println(symptom + ": " + e.getMessage());
                    }
                    samples.addSample(tmpSample);
                }
                
                List<AttributeDictDTO> attributeDictDTO = new AttributeDictDao().getAttributeList(true);
                Set<ObjectAttributesDTO> objectAttributesDTO = new ObjectAttributesDao().getObjectAttributes(estimate.getEstimate().getObjects().getId());
                int i = 1;
                for(AttributeDictDTO attributeDict : attributeDictDTO) {
                	for(ObjectAttributesDTO objectAttributes : objectAttributesDTO) {
                		if(attributeDict.getAttributeName().equals(objectAttributes.getAttribute())) {
                			i++;
                			sample.setAttributeValue(i, objectAttributes.getAttributeValue());
                		}
                			
                	}
                }
                
            }
            samples.shuffleSamples();
    }
    
    private List<ObjectHistoryViewer> rebuildEstimateListByMode(List<ObjectHistoryViewer> baseEstimateView, int mode){
            List<ObjectHistoryViewer> estimateView = new ArrayList<ObjectHistoryViewer>();
            Set<String> secondLevelSymptomsSet = knowledgeBase.getSecondLevelSymptoms();
            Set<String> similarSymptomsSet = knowledgeBase.getSimilarSymptoms();
            
            if ((mode==0) || (mode>3)) {
                    return baseEstimateView;
            }
            else if (mode==1) {
                    for (ObjectHistoryViewer view: baseEstimateView) {
                            List<String> symptoms = view.getSymptomsAsList();
                            Set<String> symptomsSet = new HashSet<String>();
                            
                            for (String symptom: symptoms) {
                                    if (secondLevelSymptomsSet.contains(symptom)) {
                                            symptom = knowledgeBase.getSymptomGeneralization(symptom);
                                    }
                                    symptomsSet.add(symptom);
                            }
                            
                            List<SymptomDTO> tmpSymptoms = new ArrayList<SymptomDTO>();
                            for (String newSymptom: symptomsSet)
                            	tmpSymptoms.add(new SymptomDTO(newSymptom));
                            
                            view.setSymptoms(tmpSymptoms);
                            estimateView.add(view);
                    }
            }
            else if (mode==2) {
                    for (ObjectHistoryViewer view: baseEstimateView) {
                            List<String> symptoms = view.getSymptomsAsList();
                            Set<String> symptomsSet = new HashSet<String>();
                            
                            for (String symptom: symptoms) {
                                    if (secondLevelSymptomsSet.contains(symptom)) {
                                            symptomsSet.add(symptom);
                                            symptom = knowledgeBase.getSymptomGeneralization(symptom);
                                    }
                                    symptomsSet.add(symptom);
                            }
                            
                            List<SymptomDTO> tmpSymptoms = new ArrayList<SymptomDTO>();
                            for (String newSymptom: symptomsSet) 
                            	tmpSymptoms.add(new SymptomDTO(newSymptom));
                            
                            view.setSymptoms(tmpSymptoms);
                            estimateView.add(view);
                    }
            }
            else if (mode==3) {
                    for (ObjectHistoryViewer view: baseEstimateView) {
                            List<String> symptoms = view.getSymptomsAsList();
                            Set<String> symptomsSet = new HashSet<String>();
                            
                            for (String symptom: symptoms) {
                                    if (similarSymptomsSet.contains(symptom)) {
                                            symptomsSet.add(symptom);
                                            symptom = knowledgeBase.getSimilarSymptom(symptom);
                                    }
                                    symptomsSet.add(symptom);
                            }
                            
                            List<SymptomDTO> tmpSymptoms = new ArrayList<SymptomDTO>();
                            for (String newSymptom: symptomsSet) 
                            	tmpSymptoms.add(new SymptomDTO(newSymptom));
                            
                            view.setSymptoms(tmpSymptoms);
                            estimateView.add(view);
                    }
            }
            return estimateView;
    }

    public DiagnoserKnowledgeBase getKnowledgeBase() {
            return knowledgeBase;
    }
}
